package com.lhl.jwt.aop;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.util.ContentCachingRequestWrapper;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Objects;

/**
 * @className: WebApiLog
 * @description: TODO 类描述
 * @author: king
 * @date: 2020-09-08 14:15
 **/
@Aspect
@Slf4j
@Component
public class WebApiLog {
    private static final String START_TIME = "request-start";
    private static final String FORM_CONTENT_TYPE = "multipart/form-data";

    /**
     * 切入点
     */
    @Pointcut("@within(org.springframework.web.bind.annotation.RestController)")
    public void log() {
    }

    /**
     * 前置操作
     *
     * @param point
     *            切入点
     */
    @Before("log()")
    public void beforeLog(JoinPoint point) throws IOException {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
        log.info("【请求 URL】：{}", request.getRequestURL());
        log.info("【请求 IP】：{}", request.getRemoteAddr());
        log.info("【请求类名】：{}，【请求方法名】：{}", point.getSignature().getDeclaringTypeName(), point.getSignature().getName());

        //获取所有参数方法一
        ContentCachingRequestWrapper wrapper = new ContentCachingRequestWrapper(request);
        String jsonBody = IOUtils.toString(new ByteArrayInputStream(wrapper.getContentAsByteArray()), "utf-8");
        log.debug("【请求参数】：{}", jsonBody);


//        Map<String, String[]> parameterMap = ServletUtil.getParams(request);
//        log.info("【请求参数】：{}，", JSONUtil.toJsonStr(parameterMap));
        Long start = System.currentTimeMillis();
        request.setAttribute(START_TIME, start);
    }

    /**
     * 环绕操作
     *
     * @param point
     *            切入点
     * @return 原方法返回值
     * @throws Throwable
     *             异常信息
     */
    @Around("log()")
    public Object aroundLog(ProceedingJoinPoint point) throws Throwable {
        Object result = point.proceed();
        log.info("【返回值】：{}", JSONUtil.toJsonStr(result));
        return result;
    }

    /**
     * 后置操作
     */
    @AfterReturning("log()")
    public void afterReturning() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();

        Long start = (Long)request.getAttribute(START_TIME);
        Long end = System.currentTimeMillis();
        log.info("【请求耗时】：{}毫秒", end - start);
    }
}